package com.gopay.common.trace.helper;

import com.gopay.common.trace.LogConst;
import com.gopay.common.trace.TraceLog;
import com.gopay.common.trace.TraceLogUtils;
import com.gopay.common.trace.def.Span;
import com.gopay.common.trace.def.Tracer;
import com.gopay.common.trace.enums.TraceType;
import com.gopay.common.trace.hessian.HessianHeaderContext;
import com.gopay.common.trace.support.GenTraceId;
import com.gopay.common.trace.util.SamplingUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;

/**
 * @author ddh02
 * @LogRpcClientHelper
 * @2017/5/19 9:02  www.gopay.com.cn Inc.All rights reserved.
 */


public class LogRpcClientHelper extends LogAbstractHelper {
    @Override
    public void before(Object... args) {

        try {
            Method method = (Method) args[1];

            spanName = method.getDeclaringClass().getSimpleName() + "." + method.getName();

            if (StringUtils.isNotBlank(tid)) {
                //执行前  将tid 放入header中
                HessianHeaderContext.getContext().addHeader(LogConst.TID, tid);
            }
            //add by zyt,2017-12-15，解决定时任务，或将rpc client作为第一个拦截日志的点。的情况下，没有tid，从而不记录日志的问题
            else {
                tid = GenTraceId.genUUID();
                logContext.setTid(tid);
                HessianHeaderContext.getContext().addHeader(LogConst.TID, tid);
            }

            count = logContext.incrCount();//当前线程计数加一
            if (count != null) {
                //生成子span
                /*Tracer.getTracer()
                            .newSpan(method.getDeclaringClass().getSimpleName() + "." + method.getName(),
                                    TraceType.RPC);
    */
                span =  tracer.genSpan(tid, spanName, TraceType.RPC);

                //add by zyt,把生成的span放入logContext
                logContext.setSpan(count, span);

                //放入 子span
                HessianHeaderContext.getContext().addHeader(LogConst.SPANID, span.getId());
                HessianHeaderContext.getContext().addHeader(LogConst.SPANNAME, spanName);
                //设置 指标 cs 和cr
                tracer.clientSend(span, null, startTime);
            }
        } catch (Exception e) {
            printSelfException(e, "rpc客户端 before 阶段自身异常！");
        }

    }

    @Override
    public void after(Object... args) {

        try {
            logContext.dncrCount(); //执行完后 线程计数减一

            long end = System.currentTimeMillis();

            Span ps = logContext.getSpan(count - 1);

            if (ps != null) {
                //deleted by zyt,放到外面
                //tracer.clientReceive(span, null, end);
                logContext.setSpan(count, span);
                ps.addChild(span);
            }

            //add by zyt,打印日志
            tracer.clientReceive(span, null, end);  //ss
            tracer.endAndShow(span);
        /*if(StringUtils.isBlank(tid)){
            if(SamplingUtils.isSelected()){
                logger.info("hessian {}.{} invoke cs={} cr={} time ={}",
                        new Object[]{
                                method.getDeclaringClass().getSimpleName(),
                                method.getName(),
                                startTime, end,
                                end - startTime});
            }
        }*/
        } catch (Exception e) {
            printSelfException(e, "rpc客户端 after 阶段自身异常！");
        }

    }

    @Override
    public void ex(Throwable throwable) {

        commonProcessEx(throwable);

    }

    @Override
    public TraceType getTraceType() {
        return TraceType.RPC;
    }
}
